﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace ShevaEngine.Core.Modules.Models
{

    /// <summary>
    /// A structure that contains information for a bindpose skin offset.
    /// Represents the inverse bind pose for a bone.
    /// </summary>
    [ContentSerializerRuntimeTypeAttribute("ShevaEngine.Core.Modules.Models.SkinInfo, ShevaEngine2")]
    public struct SkinInfo
    {
        /// <summary>The name of the bone attached to the transform.</summary>
        public string BoneName;
        /// <summary>The transform for the bone.</summary>
        public Matrix InverseBindPoseTransform;
        /// <summary>The index in the MatrixPalette for the bone.</summary>
        public int PaletteIndex;
        /// <summary>The index of the bone.</summary>
        public int BoneIndex;

        /// <summary>
        /// Creates a new SkinInfo.
        /// </summary>
        /// <param name="name">The name of the bone attached to the transform.</param>
        /// <param name="inverseBindPoseTransform">The inverse bind pose transform for the bone.</param>
        /// <param name="paletteIndex">The index in the MatrixPalette for the bone.</param>
        /// <param name="boneIndex">The index of the bone.</param>
        public SkinInfo(string name, Matrix inverseBindPoseTransform,
            int paletteIndex, int boneIndex)
        {
            this.BoneName = name;
            this.InverseBindPoseTransform = inverseBindPoseTransform;
            this.PaletteIndex = paletteIndex;
            this.BoneIndex = boneIndex;
        }
    }

    /// <summary>
    /// A collection of SkinInfo objects.
    /// </summary>
    [ContentSerializerRuntimeTypeAttribute("ShevaEngine.Core.Modules.Models.SkinInfoCollection, ShevaEngine2")]
    public class SkinInfoCollection : List<SkinInfo>
    {
        /// <summary>
        /// Konstruktor.
        /// </summary>
        public SkinInfoCollection()
            : base()
        {
        }

        /// <summary>
        /// Finds the skinning info for the model and calculates the inverse
        /// reference poses required for animation.
        /// </summary>
        /// <param name="model">The model that contains the skinning info.</param>
        /// <returns>A collection of SkinInfo objects.</returns>
        public static SkinInfoCollection FromModel(Model model)
        {
            // This is created in the content pipeline
            Dictionary<string, object> modelTagData =
                    (Dictionary<string, object>)model.Tag;
            // An array of bone names that are used by the palette
            SkinInfoCollection[] info = (SkinInfoCollection[])modelTagData["SkinInfo"];
            return info[0];
        }
    }
}